package com.yllt4cloud.ddauth.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.yllt4cloud.common.core.constant.CacheConstants;
import com.yllt4cloud.common.ddbase.constant.AuthorityConstants;
import com.yllt4cloud.common.ddbase.constant.GlobalConstants;
import com.yllt4cloud.common.ddbase.constant.RedisConstants;
import com.yllt4cloud.common.ddbase.constant.ShouYinConstants;
import com.yllt4cloud.common.ddbase.containers.SystemConfigContainer;
import com.yllt4cloud.common.ddbase.containers.UserRoleContainer;
import com.yllt4cloud.common.ddbase.domain.Menu;
import com.yllt4cloud.common.ddbase.result.ButtonResult;
import com.yllt4cloud.common.ddbase.result.GetMenusResult;
import com.yllt4cloud.common.ddbase.result.MenuResult;
import com.yllt4cloud.common.ddbase.result.ModuleResult;
import com.yllt4cloud.common.ddbase.util.StringUtil;
import com.yllt4cloud.ddauth.mapper.AuthorityModeMapper;
import com.yllt4cloud.ddauth.mapper.MenuMapper;
import com.yllt4cloud.ddauth.service.IMenuService;
import com.yllt4cloud.ddauth.service.base.BaseService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * <br>
 * <b>功能：</b>MenuServiceImpl<br>
 * <b>作者：</b>Administrator<br>
 * <b>日期：</b> Wed Feb 13 10:26:26 CST 2019 <br>
 * <b>版权所有： 2016,yllt.com<br>
 */
@Service
@Transactional
public class MenuServiceImpl extends BaseService<Menu> implements IMenuService {
	private final static Logger log= LoggerFactory.getLogger(MenuServiceImpl.class);

	@Autowired
	private AuthorityModeMapper authorityModeMapper;

	@Autowired
	private MenuMapper mapper;


	public MenuMapper getMapper() {
		return mapper;
	}

	@Autowired
	private RedisTemplate redisTemplate;

	@Override
	public Integer insert(Menu record) {
		mapper.insert(record);
		return record.getId();
	}

	@Value("${spring.cloud.nacos.discovery.server-addr}")
	private String nacosUrl;

	/**
	 * 根据用户id ，获取菜单权限,这个方法只去第一级 第2级的  模块，菜单权限，（按钮的不获取）
	 * @param userId
	 * @param menuType  店端1 场所后台2 场所管理app3
	 * @return
	 */
	public List<Menu> queryMenuByParamRedisCache(Integer userId, Integer menuType){
		String menuTypeStr="";
		if(menuType==null){
			menuTypeStr="@_";
		}else{
			menuTypeStr=menuType+"_";
		}
		ValueOperations<Serializable, Serializable> operations = redisTemplate.opsForValue();
		//获取场所代码
		String store_code= SystemConfigContainer.instance().getCsCode();
		//线程从map  中获取 redisKey
		String redisKey= UserRoleContainer.instance().getUserMenuMap().get(userId+"");
		String save_key=store_code+ RedisConstants.usemenu_prefix+menuTypeStr+userId;
		if(redisKey!=null && redisKey.length()>0){

			Object object=redisTemplate.opsForList().range(redisKey,0,-1);
			if(object!=null){
				List<Menu> list=(List<Menu>)object;
				return list;
			}else{
				Map<String, Object> paramMap=new HashMap<String, Object>();
				paramMap.put("userId", userId);
				paramMap.put("menuType", menuType);
				List<Menu> list=mapper.queryMenuByParam(paramMap);

				//将 list 保存到缓存中
				redisTemplate.opsForList().leftPushAll(save_key,list);
				return list;
			}
		}else{
			//后台操作将缓存清空情况，重新获取
			Map<String, Object> paramMap=new HashMap<String, Object>();
			paramMap.put("userId", userId);
			paramMap.put("menuType", menuType);
			List<Menu> list=mapper.queryMenuByParam(paramMap);

			//先删除原来的缓存由于 项目重启 会，导致 UserRoleContainer.instance().getUserMenuMap() 值为空，但是redis 的缓存可能不为空
			redisTemplate.delete(save_key);
			//将 list 保存到缓存中
			redisTemplate.opsForList().leftPushAll(save_key,list);
			//将key 保存到map 中
			UserRoleContainer.instance().getUserRoleMap().put(userId+"",save_key);
			return list;
		}

	}

    /**
     * 根据参数查询菜单
     * @param paramMap
     * @return
     */
    public List<Menu> queryMenuByParam(Map<String, Object> paramMap){
        List<Menu> listMenu=mapper.queryMenuByParam(paramMap);
        return listMenu;
    }

	/**
	 * 获取用户菜单权限列表
	 * @param userId
	 * @param menuType
	 * @return
	 */
	@Cacheable(value = CacheConstants.MENU_DETAILS, key = "#userId  + '_menu'", unless = "#result == null")
	public GetMenusResult queryModule(Integer userId, Integer menuType){
		GetMenusResult getMenusResult=new GetMenusResult();
		List<ModuleResult> moduleResultList = new ArrayList<ModuleResult>();

		//获取模块
		Map<String, Object> paramMap=new HashMap<String, Object>();
		paramMap.put("userId", userId);
		paramMap.put("menuType", menuType);
		paramMap.put("parentFlag", AuthorityConstants.PARENTFLAG_MODULE);
		paramMap.put("orderBy", "PaiXuHao");
		paramMap.put("sortBy", "asc");
		List<Menu> listModel=mapper.queryMenuByParam(paramMap);

		if(listModel!=null && listModel.size()>0){   //遍历模块获取菜单的列表
			for(Menu model:listModel){
				List listService=null;
				try {
					NamingService naming = NamingFactory.createNamingService(nacosUrl);
					if(!StringUtil.isBlank(model.getCode())){
						listService=naming.getAllInstances(model.getCode());
					}
				} catch (NacosException e) {
					e.printStackTrace();
				}
				if(CollectionUtil.isNotEmpty(listService)){
					String  moduleId=model.getModuleId();  //
					ModuleResult moduleResult = new ModuleResult();
					List<MenuResult> menuResultList = new ArrayList<MenuResult>();
					// 获取菜单
					paramMap.put("parentFlag", AuthorityConstants.PARENTFLAG_MENU);
					paramMap.put("parentId", model.getId());
					List<Menu> listMenus=mapper.queryMenuByParam(paramMap);
					//遍历菜单 获取按钮
					for(Menu menu:listMenus){
						MenuResult menuResult=new MenuResult();

						paramMap.put("parentFlag", AuthorityConstants.PARENTFLAG_BUTTON);
						paramMap.put("parentId", menu.getId());
						if(moduleId.equals(ShouYinConstants.BAOBIAO_FAG)){  // 如果当前的模块是  报表的模块，则报表里面的 菜单，对应的按钮 需要另外读取
							List<Menu> listButton=mapper.queryMenuByParam(paramMap);
							menuResult.setButtons(listButton);
						}
						menuResult.setMenu(menu);
						Map<String, Menu> buttonMap = new HashMap<String, Menu>();
						menuResultList.add(menuResult);
					}
					//设置模块下的菜单列表
					moduleResult.setMenus(menuResultList);
					moduleResult.setModuleCssKey(model.getModuleId());
					moduleResult.setModuleId(model.getId()+"");
					moduleResult.setModuleName(model.getName());

					moduleResultList.add(moduleResult);// 添加到 集合中
				}
			}
		}
        //设置模块 菜单 按钮
        getMenusResult.setModuleList(moduleResultList);

        List<ButtonResult>  buttonAll=new ArrayList<ButtonResult>();

		// 获取 用户顶部，店端的按钮列表，
        Map<String, Object> buttonMap=new HashMap<String, Object>();
        buttonMap.put("userId", userId);
        buttonMap.put("isButton", GlobalConstants.TRUE); //店端 ，顶部，按钮标识
        buttonMap.put("parentFlag", AuthorityConstants.PARENTFLAG_BUTTON); //按钮
        //而且url 不为空
        buttonMap.put("haveUrl", GlobalConstants.TRUE);
        buttonMap.put("orderBy", "PaiXuHao");
        buttonMap.put("sortBy", "asc");
        List<ButtonResult> buttonList= mapper.queryButtonByParam(buttonMap);
        if(buttonList!=null && buttonList.size()>0){
            buttonAll.addAll(buttonList);
        }

        // 获取所有授权方式的 ，转成按钮形式对象
        Map<String, Object> modelMap=new HashMap<String, Object>();
        modelMap.put("canQuanXianFlag", GlobalConstants.TRUE);
        //而且url 不为空
        modelMap.put("haveUrl", GlobalConstants.TRUE);
        List<ButtonResult>  buttonList_two=authorityModeMapper.queryToButton(modelMap);
        if(buttonList_two!=null && buttonList_two.size()>0){
            buttonAll.addAll(buttonList_two);
        }

        Map<String, ButtonResult> buttonResutlMap = new HashMap<String, ButtonResult>();

        for (ButtonResult buttonResult : buttonAll) {
            buttonResutlMap.put(buttonResult.getUrl(), buttonResult);
        }
        getMenusResult.setButtonResutlMap(buttonResutlMap);
		return getMenusResult;
	}


}
